﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MinToTray
{
    public class TrayMgr
    {
        static Dictionary<IntPtr, NotifyIcon> Trays = new Dictionary<IntPtr, NotifyIcon>();

        public static int GetTraysCount()
        {
            return Trays.Count;
        }

        public static void MinWindowToTray(IntPtr hWnd)
        {
            try
            {
                //// Don't minimize MDI child windows
                if (((uint)Win32.GetWindowLongPtr(hWnd, (int)WindowLongFlags.GWL_EXSTYLE) & Win32.WS_EX_MDICHILD) > 0) return;
                //// If hwnd is a child window, find parent window (e.g. minimize button in
                //// Office 2007 (ribbon interface) is in a child window)
                //if (((uint)PInvoke.GetWindowLongPtr(hwnd, (int)WindowLongFlags.GWL_STYLE) & PInvoke.WS_CHILD) > 0)
                //{
                //    hwnd = PInvoke.GetAncestor(hwnd, GetAncestorFlags.GetRoot);
                //}
            }
            catch { return; }

            if (Trays.ContainsKey(hWnd)) return;
            NotifyIcon tray = new NotifyIcon();
            tray.Tag = hWnd;
            Icon icon = null;
            switch (Trays.Count)
            {
                case 0:
                    icon = Properties.Resources.ico1;
                    break;
                case 1:
                    icon = Properties.Resources.ico2;
                    break;
                case 2:
                    icon = Properties.Resources.ico3;
                    break;
                case 3:
                    icon = Properties.Resources.ico4;
                    break;
                default:
                    icon = Properties.Resources.icoplus;
                    break;
            }
            tray.Icon = icon;
            tray.MouseClick += Tray_MouseClick;
            tray.Visible = true;
            Trays.Add(hWnd, tray);

            // Hide window
            Win32.ShowWindow(hWnd, (int)WindowShowStatus.SW_HIDE);
        }

        public static void MinForegroundWindowToTray()
        {
            var hWnd = Win32.GetForegroundWindow();
            MinWindowToTray(hWnd);
        }

        public static void RemoveTray(IntPtr hWnd)
        {
            if (Trays.ContainsKey(hWnd))
            {
                var tray = Trays[hWnd];
                tray.Dispose();
                Trays.Remove(hWnd);
            }
        }

        public static void RemoveTrayIfNeedless(IntPtr hWnd)
        {
            if (!Trays.ContainsKey(hWnd)) return; 
            if (!Win32.IsWindow(hWnd) || Win32.IsWindowVisible(hWnd))
            {
                RemoveTray(hWnd);
            }
        }

        public static void ResotreAllWindowWithoutAuth()
        {
            var traysTemp = Trays.Values.ToArray();

            foreach (var tray in traysTemp)
            {
                var hWnd = (IntPtr)tray.Tag;
                RestoreTrayWindow(hWnd);
            }
        }

        public static void CloseAllWindowWithoutAuth()
        {
            var traysTemp = Trays.Values.ToArray();

            foreach (var tray in traysTemp)
            {
                var hWnd = (IntPtr)tray.Tag;
                CloseTrayWindow(hWnd);
            }
        }

        static void Tray_MouseClick(object sender, MouseEventArgs e)
        { 
            IntPtr hWnd = (IntPtr)(sender as NotifyIcon).Tag;
              
            if (e.Button == MouseButtons.Left)
            {
                RestoreWindowWithAuth(hWnd);
            }
            else if (e.Button == MouseButtons.Middle)
            {
                CloseTrayWindow(hWnd);
            }
        }
         
        static void RestoreWindowWithAuth(IntPtr hWnd)
        {
            if (AuthMgr.Auth(hWnd))
            {
                RestoreTrayWindow(hWnd);
            }
        }

        static void RestoreTrayWindow(IntPtr hWnd)
        {
            Win32.ShowWindow(hWnd, (int)WindowShowStatus.SW_SHOW);
            Task.Factory.StartNew(() => { Thread.Sleep(200); Win32.SetForegroundWindow(hWnd); });
           
            RemoveTray(hWnd);
        }

        static void CloseWindowWithAuth(IntPtr hWnd)
        {
            if (AuthMgr.Auth(hWnd))
            {
                CloseTrayWindow(hWnd);
            }
        }

        static void CloseTrayWindow(IntPtr hWnd)
        {
            Win32.PostMessage(hWnd, WinMsg.WM_CLOSE, 0, 0);
            Thread.Sleep(50);
            RemoveTray(hWnd);
            AuthMgr.CancelAuth(hWnd);
        }
    }

}
